/**
 * 
 */
package slhs.tempo.pivotTableUtilities;

import java.awt.Color;
import java.awt.Component;
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Set;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;

import org.mlc.swing.layout.LayoutConstraintsManager;
import org.openswing.swing.wizard.client.WizardInnerPanel;
import org.openswing.swing.wizard.client.WizardPanel;

import slhs.tempo.TableAnalyzer.ConcreteTableModelListener;
import slhs.tempo.TableAnalyzer.FilterControlsPanelHandler;
import slhs.tempo.TableAnalyzer.IntegerField;
import slhs.tempo.TableAnalyzer.SaveCurrentState;
import slhs.tempo.TableAnalyzer.TableColumnAdjuster;
import slhs.tempo.TableAnalyzer.TablePanelHandler;
import slhs.tempo.scriptGenerator.UtilityConstants;

import com.jgoodies.forms.factories.DefaultComponentFactory;

/**
 * PivotWizardThirdPanel.java
 * 
 * @author Swapnil Devikar
 * 
 */
public class PivotWizardSecondPanel extends WizardInnerPanel implements ActionListener {
    private static final String SECOND_PANEL_LAYOUT_XML_FILE = "SECOND_PANEL_LAYOUT.XML";
    public static final String SCREEN_ID = "SECOND";
    private static final String INSERT_NEW_TAB_MESSAGE = "Specify name for new sheet";

    private Component defaultControlsSeperator;
    private Component optionalControlsSeperator;

    private IntegerField ignoreReactionTimeBelowTextField;
    private IntegerField ignoreReactionTimeAboveTextField;

    private JCheckBox ignoreReactionTimeBelowCheckBox;
    private JCheckBox ignoreNonExpItemsCheckBox;
    private JCheckBox ignoreNonCtlRelItemsCheckBox;
    private JCheckBox ignoreReactionTimeAboveCheckBox;
    private JCheckBox ignoreIncorrectResponseItems;
    private JCheckBox insertZScoreColumnCheckBox;
    private JCheckBox insertMeanColumnCheckbox;
    private JCheckBox insertStandardDeviationsColumnCheckBox;

    private JButton ignoreReactionTimeAboveUpdateButton;
    private JButton ignoreReactionTimeBelowUpdateButton;

    private TablePanelHandler tablePanelHandlerObject;
    private WizardPanel wizardPanel;

    private StatsCalculator statsCalculator;
    private static SubjectStat[] stats;

    private Object[] meanValuesArray;
    private Object[] standardDeviationArray;
    private Object[] zScoreArray;

    private Object[] controlMeanValuesArray;
    private Object[] controlStandardDeviationArray;
    private Object[] controlZScoreArray;

    private Object[] relatedMeanValuesArray;
    private Object[] relatedStandardDeviationArray;
    private Object[] relatedZScoreArray;

    private JTable table;

    public PivotWizardSecondPanel(TablePanelHandler tablePanelHandlerObject, WizardPanel wizardPanel) {
	this.tablePanelHandlerObject = tablePanelHandlerObject;
	this.wizardPanel = wizardPanel;
	initComponents();
	addComponents();

    }

    /**
     * Helper method to initialize components
     */
    private void initComponents() {
	defaultControlsSeperator = DefaultComponentFactory.getInstance().createSeparator("Default Controls",
		SwingConstants.CENTER);
	optionalControlsSeperator = DefaultComponentFactory.getInstance().createSeparator("Optional Controls",
		SwingConstants.CENTER);

	ignoreReactionTimeAboveTextField = new IntegerField(4);
	ignoreReactionTimeBelowTextField = new IntegerField(4);

	ignoreReactionTimeAboveUpdateButton = new JButton("Update");
	ignoreReactionTimeBelowUpdateButton = new JButton("Update");

	ignoreReactionTimeBelowCheckBox = new JCheckBox("Ignore Reaction Time Below");
	ignoreNonExpItemsCheckBox = new JCheckBox("Ignore Non-Experimental Items");
	ignoreNonCtlRelItemsCheckBox = new JCheckBox("Ignore non Ctl/Rel Items");
	ignoreIncorrectResponseItems = new JCheckBox("Ignore Incorrect Responses");
	ignoreReactionTimeAboveCheckBox = new JCheckBox("Ignore Reaction Time Above");
	insertZScoreColumnCheckBox = new JCheckBox("Insert Z-Score Column");
	insertMeanColumnCheckbox = new JCheckBox("Insert Mean Column");
	insertStandardDeviationsColumnCheckBox = new JCheckBox("Insert Standard Deviations Column");
    }

    /**
     * Helper method to add components
     */
    private void addComponents() {
	LayoutConstraintsManager layoutConstraintsManager = LayoutConstraintsManager.getLayoutConstraintsManager(this
		.getClass().getResourceAsStream(SECOND_PANEL_LAYOUT_XML_FILE));
	LayoutManager panelLayout = layoutConstraintsManager.createLayout("panel", this);
	this.setLayout(panelLayout);
	this.add(ignoreReactionTimeAboveCheckBox, "ignoreReactionTimeAboveCheckBox");
	this.add(defaultControlsSeperator, "defaultControlsSeperator");
	this.add(ignoreIncorrectResponseItems, "ignoreIncorrectResponseItems");
	this.add(ignoreReactionTimeAboveTextField, "ignoreReactionTimeAboveTextField");
	this.add(insertMeanColumnCheckbox, "insertMeanColumnCheckbox");
	this.add(ignoreReactionTimeBelowTextField, "ignoreReactionTimeBelowTextField");
	this.add(insertZScoreColumnCheckBox, "insertZScoreColumnCheckBox");
	this.add(optionalControlsSeperator, "optionalControlsSeperator");
	this.add(ignoreReactionTimeBelowCheckBox, "ignoreReactionTimeBelowCheckBox");
	this.add(ignoreNonExpItemsCheckBox, "ignoreNonExpItemsCheckBox");
	this.add(ignoreNonCtlRelItemsCheckBox, "ignoreNonCtlRelItemsCheckBox");
	this.add(ignoreReactionTimeAboveUpdateButton, "ignoreReactionTimeAboveUpdateButton");
	this.add(ignoreReactionTimeBelowUpdateButton, "ignoreReactionTimeBelowUpdateButton");
	this.add(insertStandardDeviationsColumnCheckBox, "insertStandardDeviationsColumnCheckBox");

	// cotrol configurations
	this.ignoreReactionTimeAboveUpdateButton.setEnabled(false);
	this.ignoreReactionTimeBelowUpdateButton.setEnabled(false);

	this.ignoreNonExpItemsCheckBox.addActionListener(this);
	this.ignoreIncorrectResponseItems.addActionListener(this);
	this.ignoreReactionTimeAboveCheckBox.addActionListener(this);
	this.ignoreReactionTimeBelowCheckBox.addActionListener(this);
	this.ignoreReactionTimeAboveUpdateButton.addActionListener(this);
	this.ignoreReactionTimeBelowUpdateButton.addActionListener(this);
	this.insertZScoreColumnCheckBox.addActionListener(this);
	this.insertStandardDeviationsColumnCheckBox.addActionListener(this);

    }

    @Override
    public String getPanelId() {
	return SCREEN_ID;
    }

    /**
     * This method is automatically called by WizardPanel when the panel is showed: it can be overridden to add custom
     * logic that must be executed when the panel is showed.
     */
    @Override
    public void init() {

	// default conditions like ignore non experimental items, wrong answers etc
	if (!ignoreIncorrectResponseItems.isSelected()) {
	    this.ignoreIncorrectResponseItems.setSelected(true);
	    FilterControlsPanelHandler.checkFilterIncorrectResponseCheckBox();
	}

	if (!ignoreNonExpItemsCheckBox.isSelected()) {
	    this.ignoreNonExpItemsCheckBox.setSelected(true);
	    FilterControlsPanelHandler.checkIgnoreNonExpItemsCheckBox();

	}

	if (!ignoreNonCtlRelItemsCheckBox.isSelected()) {
	    this.ignoreNonCtlRelItemsCheckBox.setSelected(true);

	}

	if (!ignoreReactionTimeAboveCheckBox.isSelected()) {
	    this.ignoreReactionTimeAboveCheckBox.setSelected(false);
	}

	if (!ignoreReactionTimeBelowCheckBox.isSelected()) {
	    this.ignoreReactionTimeBelowCheckBox.setSelected(false);
	}

	if (!ignoreReactionTimeAboveTextField.isEnabled()) {
	    this.ignoreReactionTimeAboveTextField.setEnabled(false);
	}

	if (!ignoreReactionTimeBelowTextField.isEnabled()) {
	    this.ignoreReactionTimeBelowTextField.setEnabled(false);
	}

	if (insertMeanColumnCheckbox.isSelected()) {
	    this.insertMeanColumnCheckbox.setSelected(false);
	}
	if (insertMeanColumnCheckbox.isEnabled() == false) {
	    insertMeanColumnCheckbox.setEnabled(true);
	}
	if (insertStandardDeviationsColumnCheckBox.isSelected()) {
	    this.insertStandardDeviationsColumnCheckBox.setSelected(false);
	}
	if (insertZScoreColumnCheckBox.isSelected()) {
	    this.insertZScoreColumnCheckBox.setSelected(false);
	}

    }

    /**
     * This method could be overridden.
     * 
     * @return image name; null if no image is required
     */
    @Override
    public String getImageName() {
	return "setup2.gif";
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
     */
    @Override
    public void actionPerformed(ActionEvent event) {
	Object source = event.getSource();
	// ignore non experimental items
	if (source.equals(this.ignoreNonExpItemsCheckBox)) {
	    FilterControlsPanelHandler.checkIgnoreNonExpItemsCheckBox();
	}
	// Filter incorrect responses
	else if (source.equals(this.ignoreIncorrectResponseItems)) {
	    FilterControlsPanelHandler.checkFilterIncorrectResponseCheckBox();
	}
	// Upper limit on reaction time
	else if (source.equals(this.ignoreReactionTimeAboveCheckBox)) {
	    FilterControlsPanelHandler.checkIgnoreReactionTimeAboveCheckBox();
	    if (this.ignoreReactionTimeAboveCheckBox.isSelected()) {
		this.ignoreReactionTimeAboveTextField.setEnabled(true);
		this.ignoreReactionTimeAboveUpdateButton.setEnabled(true);
		this.ignoreReactionTimeAboveTextField.setBackground(Color.YELLOW);

	    } else {
		this.ignoreReactionTimeAboveTextField.setEnabled(false);
		this.ignoreReactionTimeAboveTextField.setBackground(Color.LIGHT_GRAY);
		this.ignoreReactionTimeAboveTextField.setText("");
		this.ignoreReactionTimeAboveUpdateButton.setEnabled(false);

	    }
	} else if (source.equals(this.ignoreReactionTimeBelowCheckBox)) {
	    FilterControlsPanelHandler.checkIgnoreReactionTimeBelowCheckBox();
	    if (this.ignoreReactionTimeBelowCheckBox.isSelected()) {
		this.ignoreReactionTimeBelowTextField.setEnabled(true);
		this.ignoreReactionTimeBelowUpdateButton.setEnabled(true);
		this.ignoreReactionTimeBelowTextField.setBackground(Color.YELLOW);

	    } else {
		this.ignoreReactionTimeBelowTextField.setEnabled(false);
		this.ignoreReactionTimeBelowTextField.setBackground(Color.LIGHT_GRAY);
		this.ignoreReactionTimeBelowTextField.setText("");
		this.ignoreReactionTimeBelowUpdateButton.setEnabled(false);

	    }

	} else if (source.equals(this.ignoreNonCtlRelItemsCheckBox)) {
	    // ignore non ctl/rel items
	} else if (source.equals(this.insertMeanColumnCheckbox)) {
	    // no visual action is required here
	} else if (source.equals(this.insertZScoreColumnCheckBox)) {
	    if (this.insertZScoreColumnCheckBox.isSelected()) {
		this.insertMeanColumnCheckbox.setSelected(true);
		this.insertStandardDeviationsColumnCheckBox.setSelected(true);
		this.insertMeanColumnCheckbox.setEnabled(false);
		this.insertStandardDeviationsColumnCheckBox.setEnabled(false);
	    } else {
		this.insertMeanColumnCheckbox.setEnabled(true);
		this.insertStandardDeviationsColumnCheckBox.setEnabled(true);
	    }
	} else if (source.equals(this.insertStandardDeviationsColumnCheckBox)) {
	    if (this.insertStandardDeviationsColumnCheckBox.isSelected()) {
		this.insertMeanColumnCheckbox.setSelected(true);
		this.insertMeanColumnCheckbox.setEnabled(false);
	    } else {
		this.insertMeanColumnCheckbox.setEnabled(true);
	    }
	}
	// update table with upper limit on reaction time
	else if (source.equals(this.ignoreReactionTimeAboveUpdateButton)) {
	    // if unchecked, check the box on the filter controls panel
	    String upperLimit = this.ignoreReactionTimeAboveTextField.getText();
	    if (upperLimit != null) {
		FilterControlsPanelHandler.upperLimitResponseTimeTextField.setText(upperLimit);
		FilterControlsPanelHandler.ignoreResponseTimeAboveUpdateButton.doClick();
	    }

	} else if (source.equals(this.ignoreReactionTimeBelowUpdateButton)) {
	    // if unchecked, check the box on the filter controls panel
	    String lowerLimit = this.ignoreReactionTimeBelowTextField.getText();
	    if (lowerLimit != null) {
		FilterControlsPanelHandler.lowerLimitResponseTimeTextField.setText(lowerLimit);
		FilterControlsPanelHandler.ignoreResponseTimeBelowUpdateButton.doClick();
	    }
	}
    }

    /**
     * Save current state of the table and insert a new tab holding the updated table
     * 
     * @return tabId - Name of the inserted tab
     */
    public String saveCurrentState() {
	TableModel originalModel = ConcreteTableModelListener.getUpdatedModel();
	JTable newTable = new JTable(originalModel.getRowCount(), originalModel.getColumnCount());

	for (int oldModelRowIndex = 0; oldModelRowIndex < originalModel.getRowCount(); oldModelRowIndex++) {
	    for (int oldModelColumnIndex = 0; oldModelColumnIndex < originalModel.getColumnCount(); oldModelColumnIndex++) {
		newTable.setValueAt(originalModel.getValueAt(oldModelRowIndex, oldModelColumnIndex), oldModelRowIndex,
			oldModelColumnIndex);
	    }
	}

	/**
	 * Set the column model for new table
	 * */
	TableColumnModel originalcolumnModel = tablePanelHandlerObject.getTable().getColumnModel();
	int columnCount = originalcolumnModel.getColumnCount();
	String[] columnIdentifiers = new String[columnCount];
	for (int columnIndex = 0; columnIndex < columnCount; columnIndex++) {
	    String columnName = originalcolumnModel.getColumn(columnIndex).getIdentifier().toString();
	    columnIdentifiers[columnIndex] = columnName;

	}
	// column names
	DefaultTableModel newModel = (DefaultTableModel) newTable.getModel();
	newModel.setColumnIdentifiers(columnIdentifiers);

	// Visual Sugar
	newTable.setGridColor(Color.LIGHT_GRAY);
	newTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
	newTable.setCellSelectionEnabled(true);
	newTable.setRowSelectionAllowed(true);
	newTable.setColumnSelectionAllowed(true);
	new TableColumnAdjuster(newTable).adjustColumns();
	JScrollPane newTableScrollPane = new JScrollPane(newTable);
	newTableScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
	newTableScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

	String tabId = JOptionPane.showInputDialog(INSERT_NEW_TAB_MESSAGE, "");
	if (tabId.equals("")) {
	    tabId = new Integer(UtilityConstants.tabCount + 1).toString();
	}
	tablePanelHandlerObject.addNewTab(tabId, newTableScrollPane);
	SaveCurrentState.tableNameObjectHashmap.put(new Integer(UtilityConstants.tabCount++), newTable);
	return tabId;
    }

    /**
     * @return checked state of the insert mean checkbox
     */
    public boolean isInsertMeanChecked() {
	return insertMeanColumnCheckbox.isSelected();
    }

    /**
     * @return enabled state of the insert mean checkbox
     */
    public boolean isInsertMeanEnabled() {
	return insertMeanColumnCheckbox.isEnabled();
    }

    /**
     * @return true if standard deviation checkbox selected, else false
     */
    public boolean isInsertStandardDeviationChecked() {

	return this.insertStandardDeviationsColumnCheckBox.isSelected();
    }

    /**
     * @return true id standard deviation checkbox selected, else false
     */
    public boolean isInsertStandardDeviationEnabled() {

	return this.insertStandardDeviationsColumnCheckBox.isEnabled();
    }

    /**
     * @return Checked state of the insert z score column checkbox
     */
    public boolean isInsertZScoreChecked() {
	return insertZScoreColumnCheckBox.isSelected();
    }

    /**
     * Generate overall or conditional statistics
     * 
     * @param current
     *            visible tab id
     * */
    protected void generateStats(String tabId) {
	statsCalculator = new StatsCalculator(this.tablePanelHandlerObject);
	Set<String> probePointSet = statsCalculator.preProcessProbePointStrings();
	int numberOfSubjects = statsCalculator.getNumberOfSubjects();
	table = TablePanelHandler.getTableOnTab(tabId);

	meanValuesArray = getOverallMeanValuesArray(table, statsCalculator);
	standardDeviationArray = getStandardDeviationsArray(table);
	zScoreArray = getOverallZscoresArray(table, numberOfSubjects);

	// generate conditional stats
	controlMeanValuesArray = getControlMeanValuesArray(table, statsCalculator);
	controlStandardDeviationArray = getControlStandardDeviationsArray(table);
	controlZScoreArray = getControlZscoresArray(table, numberOfSubjects);

	relatedMeanValuesArray = getRelatedMeanValuesArray(table, statsCalculator);
	relatedStandardDeviationArray = getRelatedStandardDeviationsArray(table);
	relatedZScoreArray = getRelatedZscoresArray(numberOfSubjects);

	// conditional stats across and per probe point
	getMeanValuesForProbePointsAcrossAllReactionTimes(probePointSet);
	getStdDevValuesArrayForProbePointsAcrossConditions(probePointSet);

	getMeanValuesArrayForProbePointsForControlReactionTimes(probePointSet);
	getStdDevValuesArrayForProbePointsForControlReactionTimes(probePointSet);

	getMeanValuesArrayForProbePointsForRelatedReactionTimes(probePointSet);
	getStdDevValuesArrayForProbePointsForRelatedReactionTimes(probePointSet);

    }

    /**
     * Insert mean, sd and z score columns at the end of the table
     * 
     * @param tabId
     */
    protected void insertStatsColumns() {

	PivotWizardFirstPanel firstPanel = (PivotWizardFirstPanel) wizardPanel
		.getPanel(PivotWizardFirstPanel.SCREEN_ID);

	if (firstPanel.isOverallAnalysisPerSubjectAcrossConditionsSelected()) {
	    insertColumn(table, UtilityConstants.OVERALL_MEAN_COLUMN_IDENTIFIER, meanValuesArray);

	    // additionally, if standard deviation column is required, insert that
	    if (this.insertStandardDeviationsColumnCheckBox.isSelected()) {
		insertColumn(table, UtilityConstants.OVERALL_SD_COLUMN_IDENTIFIER, standardDeviationArray);

	    }

	    // also, if insert z score column if option is selected, do that
	    if (this.insertZScoreColumnCheckBox.isSelected()) {
		insertColumn(table, UtilityConstants.OVERALL_Z_SCORE_COLUMN_IDENTIFIER, zScoreArray);

	    }

	} else {
	    insertColumn(table, UtilityConstants.CONTROL_MEAN_COLUMN_IDENTIFIER, controlMeanValuesArray);
	    insertColumn(table, UtilityConstants.RELATED_MEAN_COLUMN_IDENTIFIER, relatedMeanValuesArray);

	    // additionally, if standard deviation column is required, insert that
	    if (this.insertStandardDeviationsColumnCheckBox.isSelected()) {
		insertColumn(table, UtilityConstants.CONTROL_SD_COLUMN_IDENTIFIER, controlStandardDeviationArray);
		insertColumn(table, UtilityConstants.RELATED_SD_COLUMN_IDENTIFIER, relatedStandardDeviationArray);

	    }

	    // also, if insert z score column if option is selected, do that
	    if (this.insertZScoreColumnCheckBox.isSelected()) {
		insertColumn(table, UtilityConstants.CONTROL_Z_SCORE_COLUMN_IDENTIFIER, controlZScoreArray);
		insertColumn(table, UtilityConstants.RELATED_Z_SCORE_COLUMN_IDENTIFIER, relatedZScoreArray);

	    }

	}

    }

    /**
     * @param Table
     *            for which z-scores are to be calculated
     * @return array containing z scores
     * 
     */
    private Object[] getOverallZscoresArray(JTable table, int numberOfSubjects) {

	stats = statsCalculator.generateOverallZscoreStats();
	ArrayList<Double> overallZScores = new ArrayList<Double>();
	for (int subjectIndex = 0; subjectIndex < numberOfSubjects; subjectIndex++) {
	    ArrayList<Double> currentSubjectZScores = stats[subjectIndex].getOverAllZscore();
	    for (double zscore : currentSubjectZScores) {
		overallZScores.add(zscore);
	    }
	}
	return overallZScores.toArray();
    }

    /**
     * @param table
     * @param numberOfSubjects
     * @return
     */
    private Object[] getControlZscoresArray(JTable table, int numberOfSubjects) {
	stats = statsCalculator.generateControlZscoreStats();
	ArrayList<Double> controlZScores = new ArrayList<Double>();
	for (int subjectIndex = 0; subjectIndex < numberOfSubjects; subjectIndex++) {
	    ArrayList<Double> currentSubjectZScores = stats[subjectIndex].getControlZscores();
	    for (double zscore : currentSubjectZScores) {
		controlZScores.add(zscore);
	    }
	}
	return controlZScores.toArray();
    }

    /**
     * @param table2
     * @param numberOfSubjects
     * @return
     */
    private Object[] getRelatedZscoresArray(int numberOfSubjects) {
	stats = statsCalculator.generateRelatedZscoreStats();
	ArrayList<Double> controlZScores = new ArrayList<Double>();
	for (int subjectIndex = 0; subjectIndex < numberOfSubjects; subjectIndex++) {
	    ArrayList<Double> currentSubjectZScores = stats[subjectIndex].getRelatedZscores();
	    for (double zscore : currentSubjectZScores) {
		controlZScores.add(zscore);
	    }
	}
	return controlZScores.toArray();
    }

    /**
     * @param table
     * @param meanValues
     * @return
     */
    private Object[] getStandardDeviationsArray(JTable table) {

	stats = statsCalculator.generateOverallStandardDeviationStats();
	Object[] standardDeviations = new Object[table.getRowCount()];
	for (int tableRowIndex = 0; tableRowIndex < table.getRowCount(); tableRowIndex++) {
	    String subjectId = (String) table.getValueAt(tableRowIndex, 0);
	    int subjectIndex = getSubjectIndexById(subjectId);
	    standardDeviations[tableRowIndex] = stats[subjectIndex].getOverallStandardDeviation();
	}
	return standardDeviations;
    }

    /**
     * @param table
     * @param relatedMeanValuesArray
     * @return
     */
    private Object[] getRelatedStandardDeviationsArray(JTable table) {
	stats = statsCalculator.generateRelatedStandardDeviationStats();
	Object[] relatedStandardDeviations = new Object[table.getRowCount()];
	for (int tableRowIndex = 0; tableRowIndex < table.getRowCount(); tableRowIndex++) {
	    String subjectId = (String) table.getValueAt(tableRowIndex, 0);
	    int subjectIndex = getSubjectIndexById(subjectId);
	    relatedStandardDeviations[tableRowIndex] = stats[subjectIndex].getRelatedStandardDeviation();
	}
	return relatedStandardDeviations;
    }

    /**
     * @param table
     * @return
     */
    private Object[] getControlStandardDeviationsArray(JTable table) {
	stats = statsCalculator.generateControlStandardDeviationStats();
	Object[] controlStandardDeviations = new Object[table.getRowCount()];
	for (int tableRowIndex = 0; tableRowIndex < table.getRowCount(); tableRowIndex++) {
	    String subjectId = (String) table.getValueAt(tableRowIndex, 0);
	    int subjectIndex = getSubjectIndexById(subjectId);
	    controlStandardDeviations[tableRowIndex] = stats[subjectIndex].getControlStandardDeviation();
	}
	return controlStandardDeviations;
    }

    /**
     * @param table
     *            - Table on the current tab
     * @param statsCalculator
     * @return Array of mean values
     */
    private Object[] getOverallMeanValuesArray(JTable table, StatsCalculator statsCalculator) {
	// generate overall mean stats, populate values array and insert column

	stats = statsCalculator.generateOverallMeanStats();
	Object[] meanValues = new Object[table.getRowCount()];
	for (int tableRowIndex = 0; tableRowIndex < table.getRowCount(); tableRowIndex++) {
	    String subjectId = (String) table.getValueAt(tableRowIndex, 0);
	    int subjectIndex = getSubjectIndexById(subjectId);
	    meanValues[tableRowIndex] = stats[subjectIndex].getOverallMeanReactionTime();
	}
	return meanValues;
    }

    /**
     * @param table
     *            - Table on the current tab
     * @return Array of mean values for reactions of types control
     */
    private Object[] getControlMeanValuesArray(JTable table, StatsCalculator statsCalculator) {
	// generate overall mean stats, populate values array and insert column

	stats = statsCalculator.generateConditionalMeanStats();
	Object[] controlMeanValues = new Object[table.getRowCount()];
	for (int tableRowIndex = 0; tableRowIndex < table.getRowCount(); tableRowIndex++) {
	    String subjectId = (String) table.getValueAt(tableRowIndex, 0);
	    int subjectIndex = getSubjectIndexById(subjectId);
	    controlMeanValues[tableRowIndex] = stats[subjectIndex].getControlMeanReactionTime();
	}
	return controlMeanValues;
    }

    /**
     * @param table
     *            - Table on the current tab
     * @param statsCalculator
     *            - stats calculator class object
     * @return Array of mean values for reactions of types control
     */
    private Object[] getRelatedMeanValuesArray(JTable table, StatsCalculator statsCalculator) {
	// generate overall mean stats, populate values array and insert column

	stats = statsCalculator.generateConditionalMeanStats();
	Object[] relatedMeanValues = new Object[table.getRowCount()];
	for (int tableRowIndex = 0; tableRowIndex < table.getRowCount(); tableRowIndex++) {
	    String subjectId = (String) table.getValueAt(tableRowIndex, 0);
	    int subjectIndex = getSubjectIndexById(subjectId);
	    relatedMeanValues[tableRowIndex] = stats[subjectIndex].getRelatedMeanReactionTime();
	}
	return relatedMeanValues;
    }

    /**
     * Generate probe point based mean values across overall conditions
     * 
     * @param probePointSet
     * */
    private Object[] getMeanValuesForProbePointsAcrossAllReactionTimes(Set<String> probePointSet) {
	stats = statsCalculator.generateMeanValuesForProbePointsAcrossAllReactionTimes(probePointSet);

	return null;
    }

    /**
     * @param probePointSet
     */
    private Object[] getStdDevValuesArrayForProbePointsAcrossConditions(Set<String> probePointSet) {
	stats = statsCalculator.generateStdDevValuesForProbePointsAcrossAllReactionTimes(probePointSet);

	return null;

    }

    /**
     * @param probePointSet
     */
    private Object[] getStdDevValuesArrayForProbePointsForRelatedReactionTimes(Set<String> probePointSet) {
	stats = statsCalculator.generateStdDevValuesArrayForProbePointsForRelatedReactionTimes(probePointSet);
	return null;
    }

    /**
     * @param probePointSet
     */
    private Object[] getStdDevValuesArrayForProbePointsForControlReactionTimes(Set<String> probePointSet) {
	stats = statsCalculator.generateStdDevValuesArrayForProbePointsForControlReactionTimes(probePointSet);
	return null;
    }

    /**
     * Generate probe point based mean values across control conditions
     * */
    private Object[] getMeanValuesArrayForProbePointsForControlReactionTimes(Set<String> probePointSet) {
	stats = statsCalculator.generateMeanValuesForProbePointsAcrossControlReactionTimes(probePointSet);

	return null;
    }

    /**
     * Generate probe point based mean values across overall conditions
     * */
    private Object[] getMeanValuesArrayForProbePointsForRelatedReactionTimes(Set<String> probePointSet) {
	stats = statsCalculator.generateMeanValuesForProbePointsAcrossRelatedReactionTimes(probePointSet);

	return null;
    }

    /**
     * @param subjectId
     * @return
     */
    private int getSubjectIndexById(String subjectId) {
	int index = -1;
	String[] subjectList = this.tablePanelHandlerObject.getSubjectList();
	for (int subjectIndex = 0; subjectIndex < subjectList.length; subjectIndex++) {
	    if (subjectList[subjectIndex].equals(subjectId)) {
		index = subjectIndex;
	    }
	}
	return index;
    }

    /**
     * @param table
     *            Table in which columns are to be inserted
     * @param columnIdentifier
     *            Column header
     * @param values
     *            Array of values that go into new column
     */
    private void insertColumn(JTable table, String columnIdentifier, Object[] values) {
	TableColumn meanColumn = new TableColumn(table.getModel().getColumnCount());
	meanColumn.setHeaderValue(columnIdentifier);

	// Ensure that auto-create is off
	table.setAutoCreateColumnsFromModel(false);
	table.addColumn(meanColumn);
	DefaultTableModel model = (DefaultTableModel) table.getModel();
	model.addColumn(columnIdentifier, values);
	new TableColumnAdjuster(table);

    }
}
